class TPeerUnit{
    constructor(){
        this.clientId = "";
        this.code = "";
        this.peer = null;
        this.end = null ; 
        this.lv = null;
        this.rv = null ; 
    }
}

class TCommClient{
    constructor(){
        this.config={
            appId:"vSport" ,
            baseUrl:"https://wss.hhdata.cn:20036",
            mq:{                
                host:"gmggf8g.mqtt.iot.bj.baidubce.com",
                port:443,
                uid:"gmggf8g/peer",
                pwd:"a52bwKg22dCAuQzB"
            },
            kmsUrl: "wss://wss.hhdata.cn:8433/kurento",
            //kmsUrl: "wss://ssl.hhdata.cn:40014/kurento",
            kmsPeerOptions :{
                configuration: {
                    "iceServers": [ 
                        {
                            urls: "stun:223.68.161.139:3478"
                            //urls: "stun:223.112.194.253:40016"
                        },
                        {
                            urls: ["turn:223.68.161.139:3478"  ],
                            //urls: ["turn:223.112.194.253:40016"  ],
                            username: "kurento",
                            credential: "kurento"
                        }
                    ]
                },
                mediaConstraints: {
                    audio: true,
                    //video: {width: {exact: 1280}, height: {exact: 720}},
                    video: {
                        width: { min: 1280, ideal: 1280, max: 1920 },
                        height: { min: 720, ideal: 720 , max: 1080}
                    }
                }
            },
            kmsPeerTypes : {
                s: kurentoUtils.WebRtcPeer.WebRtcPeerSendonly,
                r: kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly,
                sr: kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv
            },
            kmsObjDB:{
                appPipeName:"appPipe",
                loadKey:"kms/loadObjs" , /* select *from T_KmsObj */
                registKey :"kms/regist" , /* insert into T_KmsObj(code , clientId , kmsId ) values (:code , :clientId , :kmsId )*/
                removeKey :"kms/remove" , /* delete from T_KmsObj where kmsId=:kmsId*/
            }
        }
        this.objs={
            client: null,
            mqClient: null,
            mqSyncBuf:{},
            codeDict:{},
            idDict:{}
        }
    }
    static cb( callback , p0,p1,p2  ){
        var me = this;
        try{
            if( callback){
                callback(p0,p1,p2);
            }
        }
        catch(er){
            console.log(er); 
        };
    }
    callApi( appId , module , ac , ps ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{
                var apiPath= [me.config.baseUrl , appId , module , ac].join("/");
                axios.post(apiPath , ps).then((res)=>{
                    if( res){
                        success(res.data);
                    }
                    else{
                        success(null);
                    }
                });
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }
    query( key , ps  ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{
                var postPs={
                    appId: me.config.appId ,
                    key:key ,
                    psJson: JSON.stringify( ps)
                }
                me.callApi("common" , "mysqldb" , "query" , postPs ).then((res)=>{
                    if( res && res.data && res.data.result){
                        success(res.data.result);
                    }
                    else{
                        success();
                    }
                });
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }
    getClient(  ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{          
                if( me.objs.client && me.objs.client!=null){
                    success(me.objs.client);
                }
                else{
                    console.log(me.config.kmsUrl);
                    kurentoClient(me.config.kmsUrl, function (error, client) {
                        if (client) {
                            me.objs.client = client;
                            success(client);
                        }
                    });
                }
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }  
    openMq( clientId , connectEvent , dicConnectEvent , receiveMsgEvent ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{      
                /*
                    var onConnect = function () {}
                    var onDisConnect = function () {}
                    var onRecMsg = function (msgData) {}
                */

                var client = null;

                var willTopic = 'hh/'+me.config.appId+"/svr";
                var willMsg = {
                    msgId:"offline" ,
                    msgBody:{
                        clientId: clientId 
                    }
                }
                var onConnect = function () {
                    var topic ='hh/'+ me.config.appId+"/"+clientId+"/#"
                    client.subscribe(topic);
                    TCommClient.cb(connectEvent);
                    success(client);
                };
                var onDisConnect = function () {
                    TCommClient.cb(dicConnectEvent);                    
                };
                var onRecMsg = function (msg) {
                    try{
                        var msgData = JSON.parse(msg.MsgContent);
                        console.log(msgData);
                        TCommClient.cb( receiveMsgEvent , msgData);
                        /*
                        if( msgData.msgId =="online"){
                            me.getClient().then(client=>{
                                var kmsId = msgData.msgBody.kmsId;
                                client.getMediaobjectById(kmsId, function(erF , obj){
                                    if( obj && obj!=null){
                                        obj.info = msgData.msgBody;
                                        me.objs.idDict[msgData.msgBody.kmsId] = obj;
                                        me.objs.codeDict[msgData.msgBody.code] = obj;
                                    }
                                    TCommClient.cb( receiveMsgEvent , msgData);
                                });
                            })
                        }
                        else if( msgData.msgId =="offline"){
                            var clientId = msgData.msgBody.clientId;
                            var objs = Object.values( me.objs.idDict).filter(function(obj){
                                return obj.info.clientId == clientId;
                            });
                            objs.forEach(function(obj){
                                if( me.objs.idDict[obj.info.kmsId]){
                                    delete me.objs.idDict[obj.info.kmsId];
                                }
                                if( me.objs.codeDict[obj.info.code]){
                                    delete me.objs.codeDict[obj.info.code];
                                }
                            });
                            TCommClient.cb( receiveMsgEvent , msgData);
                        }
                        */
                    }
                    catch(err){
                        console.log(err);
                    }
                };
                client = createMqClient(
                    me.config.mq.host,
                    me.config.mq.port,
                    me.config.mq.uid,
                    me.config.mq.pwd,
                    clientId,
                    "",
                    1, willTopic, willMsg,
                    onConnect, onDisConnect, onRecMsg
                );
                //me.objs.mqClient = client;
                var opts = client.connectionOptions;
                client.connect(opts);
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }
    openMqPro( clientId , connectEvent , dicConnectEvent , receiveMsgEvent ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{  
                var recMsg = function(msgData){
                    if( msgData.reqId && msgData.reqId!=null ){
                        var flag = me.objs.mqSyncBuf && 
                            me.objs.mqSyncBuf[msgData.reqId]
                        if( flag){
                            var timer = me.objs.mqSyncBuf[msgData.reqId].timer;
                            window.clearTimeout(timer);
                            var handler = me.objs.mqSyncBuf[msgData.reqId].handler;
                            delete me.objs.mqSyncBuf[msgData.reqId];
                            TCommClient.cb( handler , msgData);
                        }
                    }
                    else{
                        TCommClient.cb(receiveMsgEvent, msgData);
                    }
                }
                me.openMq(clientId , connectEvent , dicConnectEvent , recMsg).then(mqClient=>{
                    mqClient.sendMsg  = function(topic , msgId , msgBody  ){
                        var canFlag = mqClient && mqClient.isConnected()  ;
                        if( canFlag){
                            var msg = {
                                msgId:msgId ,
                                clientId: clientId ,
                                msgBody:msgBody  
                            }; 
                            mqClient.publish(topic , JSON.stringify(msg));
                        }

                    };
                    mqClient.sendMsgSync = function(topic , msgId , msgBody , timeout ){
                        var reqId =  ['req',( new Date()).getTime() , parseInt(1000*Math.random())].join('');
                        return new Promise( (successSync,f)=>{
                            var canFlag = mqClient  && reqId && reqId!=null && reqId.length>0;
                            if( canFlag){
                                var msg = {
                                    msgId:msgId ,
                                    clientId: clientId ,
                                    msgBody:msgBody ,
                                    reqId: reqId
                                };
                                me.objs.mqSyncBuf[reqId]={
                                    msg: msg ,
                                    handler: function(respMsg){
                                        successSync(respMsg);
                                    } 
                                }
                                mqClient.publish(topic , JSON.stringify(msg));
                                var tm = timeout && timeout>5000? timeout: 5000;
                                me.objs.mqSyncBuf[reqId].timer = window.setTimeout(function(){
                                    try{
                                        delete me.objs.mqSyncBuf[reqId];
                                        successSync();
                                    }
                                    catch(eer){
                                        console.log(eer);
                                    }
                                } , tm)
                            }
                            else{
                                successSync();
                            }
                        })

                    };
                    success(mqClient);
                })
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }
    static bindPeerEnd( peer , endpoint , callback ){
        var me = this;
        try{      
            var setCandidateEvent = function (peer, endpoint) {
                try {
                    if (peer && endpoint) {
                        endpoint.on('OnIceCandidate', function (event) {
                            var candidate = event.candidate;
                            peer.addIceCandidate(candidate);
                            //console.log(candidate);
                            console.log('candidate w->p')
                        });
                        peer.on('icecandidate', function (candidate) {
                            var iceCandidate = kurentoClient.register.complexTypes.IceCandidate(candidate);
                            endpoint.addIceCandidate(iceCandidate);
                            //console.log(iceCandidate,candidate);
                            console.log('candidate p->w')

                        });
                    }
                } catch (e) {
                    ;
                }
            }
            if (endpoint && peer) {
                peer.generateOffer(function (errorPeerGenerateOffer, sdpOffer) {
                    if (errorPeerGenerateOffer && callback) {
                        callback(errorPeerGenerateOffer, null);
                    } else {
                        endpoint.processOffer(sdpOffer, function (errorSdpOffer, sdpAnswer) {
                            if (errorSdpOffer && callback) {
                                console.log("process sdpOffer error.", errorSdpOffer)
                                callback(errorSdpOffer, null);
                            } else {
                                setCandidateEvent(peer, endpoint);
                                peer.processAnswer(sdpAnswer);
                                endpoint.gatherCandidates(function (errorGatherCandidates) {
                                    if (errorGatherCandidates && callback) {
                                        console.log('webRtcPoint gatherCandidates error.', errorGatherCandidates)
                                        callback(errorGatherCandidates, null);
                                    } else {
                                        peer.endpoint = endpoint;
                                        endpoint.peer = peer;
                                        setCandidateEvent(peer, endpoint);
                                        if (callback) {
                                            callback(null, {endpoint: endpoint, peer: peer});
                                        }
                                    }
                                });
                            }
                        });
                    }
                });
            } else {
                if (callback) {
                    callback({error: "endPoint or peer is null."}, null);
                }
            }
        }
        catch(er){
            console.log(er); 
        }
    }
    static getDevice( ){ 
        var res ={};
        return new Promise( (success , faild)=>{
            try{
                navigator.mediaDevices.enumerateDevices().then(function (devs) {
                    try {
                        for (var i = 0; i < devs.length; i++) {
                            var item = devs[i];
                            if (!res[item.kind]) {
                                res[item.kind] = []
                            }
                            res[item.kind].push(item);
                        }
                    }
                    catch (er) {
                        console.log(er)
                    }
                    success(res);
                }).catch(function () {
                    success(res);
                });
            }
            catch(er){
                console.log(er);
                success(res);
            }
        });
    }
    static setHD( obj ){ 
        return new Promise( (success , faild)=>{
            try{
                obj.setMaxVideoRecvBandwidth(6000).then(()=>{
                    return obj.setMaxVideoRecvBandwidth(6000);
                }).then(()=>{
                    return obj.setMaxVideoSendBandwidth(6000);
                }).then(()=>{
                    return obj.setMinVideoRecvBandwidth(3000);
                }).then(()=>{
                    return obj.setMinVideoSendBandwidth(3000);
                }).then(()=>{
                    success( );
                });
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
    static setCamera( peer ,  cameraDeviceId ){ 
        return new Promise( (success , faild)=>{
            try{
                if (window.rtcVideoStream) {
                    window.rtcVideoStream.getTracks().forEach(track => {
                        if( track.kind=="video") { 
                            track.stop();
                        }
                    });
                }
                window.cam = window.cam ? window.cam :"user";
                window.cam = window.cam =="user" ? "environment":"user";
                var constraints = {
                    video: {
                        deviceId : cameraDeviceId ,  
                        height:{exact:720} , 
                        width:{exact:1280}
                    }
                };
                var sender= null; 
                
                navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { 
                    try {
                        window.rtcVideoStream = stream;
                        peer.localVideo.srcObject = stream;
                        /*
                        var peerConnection = peer.peerConnection ;
                        peerConnection.removeStream(peerConnection.getLocalStreams()[0]);
                        peerConnection.addLocalStream(stream);
                        */

                        let videoTrack = stream.getVideoTracks()[0];
                        sender = peer.peerConnection.getSenders().find(function (s) {
                            return s.track.kind == videoTrack.kind;
                        });
                        sender.track.stop();
                        sender.replaceTrack(videoTrack);
                        success();
                    }
                    catch (eSet) {
                        success();
                    }
                }).catch(function (erSet) {
                    alert(erSet,2)
                    success();
                });
            }
            catch(er){
                alert('3')
                console.log(er);
                success( );
            }
        });
    }
    static switchCamera( peer ){ 
        return new Promise( (success , faild)=>{
            try{
                var action  = function(){
                    var ids =[
                        peer.devices.videoinput[0].deviceId ,
                        peer.devices.videoinput[peer.devices.videoinput.length-1].deviceId
                    ]; 
                    var cameraId = (
                        peer.cameraId  &&
                        peer.cameraId !=null &&
                        peer.cameraId.length>0 )?peer.cameraId : "";
                    cameraId = cameraId == ids[0]?ids[1]:ids[0];
                    TCommClient.setCamera(peer , cameraId ).then(()=>{
                        peer.cameraId = cameraId;
                        success();
                    })
                }
                
                TCommClient.getDevice().then(res=>{
                    peer.devices = res;
                    action();
                })
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
    static shareScreen( peer , width , height ){ 
        return new Promise( (success , faild)=>{
            try{
                var wWidth = width?width : $(window).width();
                var wHeight = height?height: $(window).height();
                var screenConstraints = {video: {width: {max:wWidth}, height: {max: wHeight}}, audio: true};
                var sender= null;
                if (navigator.mediaDevices.getDisplayMedia) {
                    navigator.mediaDevices.getDisplayMedia(screenConstraints).then(
                        function (stream) {
                            let videoTrack = stream.getVideoTracks()[0];
                            peer.localVideo.srcObject = stream;
                            sender = peer.peerConnection.getSenders().find(function (s) {
                                return s.track.kind == videoTrack.kind;
                            });
                            sender.track.stop();
                            sender.replaceTrack(videoTrack);
                            success();
                        }
                    )
                }
                else{
                    success();
                }
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
    static fullScreen( peer  ){ 
        return new Promise( (success , faild)=>{
            try{
                var element = peer.remoteVideo;
                if (element.requestFullscreen) {
                    element.requestFullscreen();
                } else if (element.msRequestFullscreen) {
                    element.msRequestFullscreen();
                } else if (element.mozRequestFullScreen) {
                    element.mozRequestFullScreen();
                } else if (element.webkitRequestFullscreen) {
                    element.webkitRequestFullscreen();
                }
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
}

var commClient = new TCommClient();

commClient.openSport = function(sportCode){
    var me = this;
    return new Promise((success,faild)=>{
        var postPs ={
            appCode : sportCode
        };
        me.callApi("vsport" , "app" , "loadApp" , postPs ).then((res)=>{
            success(res);
        });
    })

}
commClient.createSession = function(sportCode , code , clientId , pushPortCode , pullPortCode){
    var me = this;
    return new Promise((success,faild)=>{
        var postPs ={
            appCode : sportCode ,
            code: code ,
            clientId : clientId ,
            pullPortCode : pullPortCode ,
            pushPortCode : pushPortCode
        };
        me.callApi("vsport" , "app" , "createSession" , postPs ).then((res)=>{
            success(res);
        });
    })

}


var routerManager={
    tmpDatas:{},
    routes:{},
    components:{},
    registRoute( key , tmpHtml){
        try{
            var comp = {                            
                template: tmpHtml ,
                data(){
                    return {
                        tmpKey : key,
                        tmpData: {}
                    }
                },
                mounted(){
                    var tmpData = routerManager.tmpDatas[this.key];
                    tmpData = ( tmpData && tmpData!=null)?tmpData:{};
                    this.tmpData = tmpData;
                }
            }
            routerManager.components[key] = comp;
        }
        catch(er){
            console.log(er)
        }
    },
    go(vueObj , routeKey , data){
        try{
            routerManager.tmpDatas[routeKey] = data;
            var rk = routeKey.indexOf("/")==0?routeKey:"/"+routeKey;
            vueObj.$router.push("/"+rk);
        }
        catch(er){
            console.log(er);
        }
    }
}


